/**
 * @file    wifi_mesh.c
 * @author  Azolla (1228449928@qq.com)
 * @brief
 * @version 0.1
 * @date    2022-10-20
 * 
 * @copyright Copyright (c) 2022
 * */
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "freertos/queue.h" 
#include "freertos/semphr.h"

#include "cJSON.h"
#include "sys/time.h"
#include "time.h"

#include "mdf_common.h"
#include "mwifi.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_system.h"             // for uint32_t esp_random()

#include "wifi_mupgrade.h"
#include "wifi_mesh.h"

 
// #define MEMORY_DEBUG
#define TAG  "wifi_mesh"

// #define WIFI_MESH_DEBUG_ENABLE    1
 
static esp_netif_t *esp_netif = NULL;

static uint8_t selec_network = 0x00;  // 选择联网方式
 
/* FreeRTOS event group to signal when we are connected & ready to make a request */
static const uint8_t WIFI_START_EVENT = BIT0;  
static const uint8_t WIFI_STOP_EVENT  = BIT1;    
static const uint8_t WIFI_CONNECTED_EVENT     = BIT2;
static const uint8_t WIFI_DISCONNECTED_EVENT  = BIT3;     
static EventGroupHandle_t mwifi_event_group = NULL;

static QueueHandle_t mwifi_ota_queue = NULL;      // mwifi OTA队列

static const uint8_t group_id_list[1][6] = { CONFIG_MWIFI_GROUP_ID };

static mwifi_func_t mwifi_callback_func = NULL; 
 
// wifi mesh接收消息服务回调函数
void mwifi_register_callback(mwifi_func_t callback_func)
{
    if (mwifi_callback_func == NULL) {
        mwifi_callback_func = callback_func;
    }
}

bool mwifi_event_wait(uint8_t event, uint32_t wait_time) 
{
    if (mwifi_event_group == NULL) return false;
    EventBits_t uxBits = xEventGroupWaitBits(mwifi_event_group, event, pdFALSE, pdFALSE, wait_time);
    if (uxBits & event) {  
        return true;
    }  
    return false;
}
 
bool mwifi_connect_status(uint32_t wait_time) 
{
    return mwifi_event_wait(WIFI_CONNECTED_EVENT, wait_time);
}

void wifi_clear_connect_status(void)
{
    xEventGroupClearBits(mwifi_event_group, WIFI_CONNECTED_EVENT);  
}

static esp_ip4_addr_t local_ip_addr;
esp_ip4_addr_t wifi_local_ip_addr(void)
{
    return local_ip_addr;
}

static mdf_err_t mwifi_root_write_handle(const uint8_t addr[6], mwifi_data_type_t data_type, const void *data, uint16_t len) 
{
    if (len == 0 || len > MWIFI_PAYLOAD_LEN) return -0xE7;
    uint8_t dest_addr[6];
    memcpy(dest_addr, addr, 6);
    dest_addr[5] -= 2;  // STA_MAC = BLE_MAC - 2; （注意：APP用的STA_MAC; Mesh用的STA_MAC）
    mdf_err_t ret = mwifi_root_write(dest_addr, 1, &data_type, data, len, true);  
    if (ret != MDF_OK) {
        #ifdef WIFI_MESH_DEBUG_ENABLE
        MDF_LOGE("<%s> root_write_task", mdf_err_to_name(ret));
        #endif
    }
    return ret;
}
 
int app_mwifi_root_write(const uint8_t addr[6], uint8_t type, const void *data, uint16_t len) 
{
    if (mwifi_connect_status(0) == false) return -1;
    mwifi_data_type_t data_type;
    data_type.group = false;
    data_type.custom = type;  // 自定义数据类型
    data_type.upgrade = false;
    data_type.compression = false;  // 不使能数据压缩
    data_type.communicate = MWIFI_COMMUNICATE_UNICAST;
    return mwifi_root_write_handle(addr, data_type, data, len);
}

// 发送升级消息
int app_mwifi_root_upgrade_write(const uint8_t addr[6], const void *data, uint16_t len) 
{
    if (mwifi_ota_queue == NULL || mwifi_connect_status(0) == false) return -0x1;
    mwifi_data_type_t data_type;
    data_type.group = false;
    data_type.custom = 0x00;  // 自定义数据类型
    data_type.upgrade = true;
    data_type.compression = false;  // 不使能数据压缩
    data_type.communicate = MWIFI_COMMUNICATE_UNICAST;
    return mwifi_root_write_handle(addr, data_type, data, len);
}

 
int app_mwifi_root_upgrade_read(ota_result_t *packet, size_t wait_time) 
{
    if (mwifi_ota_queue == NULL || mwifi_connect_status(0) == false) return -0xE1;
    return xQueueReceive(mwifi_ota_queue, packet, wait_time);
}

void app_mwifi_root_upgrade_clear(void)
{
    xQueueReset(mwifi_ota_queue);  // 清空队列
}

static void root_read_task(void *arg)
{
    mdf_err_t ret = MDF_OK;
    EXT_RAM_ATTR static mwifi_read_t info = { 0 };  
    info.data = heap_caps_malloc(MWIFI_WRITE_DATA_LEN, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); 
    // info.data = MDF_MALLOC(MWIFI_WRITE_DATA_LEN);
    assert(info.data);

    #ifdef WIFI_MESH_DEBUG_ENABLE
    MDF_LOGI("Root read task is running");
    #endif

    while (true) {

        if (mwifi_connect_status(portMAX_DELAY) != true) {  
            continue;
        }
 
        info.size = MWIFI_WRITE_DATA_LEN;
        memset(info.data, 0x0, MWIFI_WRITE_DATA_LEN);
        ret = mwifi_root_read(info.addr, &info.data_type, info.data, &info.size, portMAX_DELAY);
        MDF_ERROR_CONTINUE(ret != MDF_OK, "<%s> root_read_task", mdf_err_to_name(ret));

        #ifdef WIFI_MESH_DEBUG_ENABLE
        MDF_LOGI("Node receive addr: " MACSTR ", type: %#x, data: %s | %d", MAC2STR(info.addr), info.data_type.custom, info.data, info.size);
        #endif

        if (info.data_type.upgrade) { // This mesh package contains upgrade data.
            // printf("mupgrade_handle seq = %d\n", info.data[2] << 8 | info.data[1]);
            // esp_log_buffer_hex("packet", info.data, info.size);
            ota_result_t packet = { 0 };
            memcpy(&packet, (ota_result_t *)info.data, sizeof(ota_result_t));
            xQueueSend(mwifi_ota_queue, &packet, 500);  // 发送队列数据
            continue;
        }

        if (mwifi_callback_func != NULL) {
            info.addr[5] += 2;  // STA_MAC = BLE_MAC - 2; （注意：APP用的STA_MAC; Mesh用的STA_MAC）
            mwifi_callback_func(info);  // 用户回调函数
        }
    }
    MDF_FREE(info.data);
    #ifdef WIFI_MESH_DEBUG_ENABLE
    MDF_LOGW("Root read task is exit");
    #endif
    vTaskDelete(NULL);
}

void app_mwifi_net_addr(uint8_t addr[6])
{
    // addr[5] += 2;  // 全部以网关的BLE_MAC作为mesh_id (BLE_MAC = STA_MAC + 2)
    esp_read_mac(addr, ESP_MAC_BT);   
}
 
// 只有root节点才能调用！
// 获取整个路由表的信息 
// node_no： 需要查询第几个节点的MAC； 0xFF: 默认查询根节点
// node_addr[MWIFI_ADDR_LEN]: 返回该节点的MAC地址
// 返回总的节点数； 
int app_mwifi_get_routing_table(uint8_t node_addr[6], uint8_t node_no)
{
    ssize_t routing_table_size = esp_mesh_get_routing_table_size();
    if (routing_table_size <= 1) {  // err.
        return routing_table_size;
    }
    mesh_addr_t *routing_table = MDF_CALLOC(routing_table_size, sizeof(mesh_addr_t));
    esp_mesh_get_routing_table(routing_table, routing_table_size * sizeof(mesh_addr_t), &routing_table_size);
#ifdef WIFI_MESH_DEBUG_ENABLE  // debug
    printf("table_size = %d; \r\n", routing_table_size);
    for (int i = 1; i < routing_table_size; i++) {
        MDF_LOGI("routing_table mac: " MACSTR, MAC2STR(routing_table[i].addr));
    }
#endif
    if (node_no >= routing_table_size) node_no = routing_table_size - 1; 
    memcpy(node_addr, routing_table[node_no].addr, MWIFI_ADDR_LEN);  
    MDF_FREE(routing_table);  // 记得释放内存！
    return routing_table_size;
}
 
static bool event_routing_table = false;
// 路由表更新
bool app_mwifi_routing_table_update(void) 
{
    bool update = event_routing_table;
    event_routing_table = false;
    return update;
}

// 获取已经连接上AP的RSSI信号强度
int8_t app_wifi_rssi(void)
{
    wifi_ap_record_t ap_info;
    esp_wifi_sta_get_ap_info(&ap_info);  // 获取已经连接的AP信息
    #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
    ESP_LOGI(TAG, "SSID: %s", ap_info.ssid);
    ESP_LOGI(TAG, "RSSI: %d", ap_info.rssi);
    ESP_LOGI(TAG, "Channel: %d", ap_info.primary);
    ESP_LOGI(TAG, "BSSID: " MACSTR "", MAC2STR(ap_info.bssid) );
    #endif
    return ap_info.rssi;
#if 0  // 扫描指定AP的信息
    uint16_t ap_number = 0;

    wifi_ap_record_t ap_info[1];
    wifi_config_t wifi_sta_cfg;

#ifdef TAG  // debug
    ESP_LOGI(TAG, "start scan");
#endif    
    if (esp_wifi_get_config(WIFI_IF_STA, &wifi_sta_cfg) != ESP_OK) { // 获取已连接的ap参数
        #ifdef TAG  // debug
        ESP_LOGW(TAG, "esp_wifi_get_config err");  
        #endif
        return -100;
    }

    wifi_scan_config_t scan_config = { 0 };
    scan_config.ssid = wifi_sta_cfg.sta.ssid;                        // 限制扫描的ap的ssid
    scan_config.bssid = wifi_sta_cfg.sta.bssid;                      // 限制扫描的ap的mac地址
    esp_wifi_scan_start(&scan_config, true);                         // 阻塞扫描ap，scan_config为扫描的参数
    
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(&ap_number));
    ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&ap_number, ap_info)); // 获取扫描到的ap信息
 
    // 获取扫描到的ap数量，因为限制了ssid和mac，因此最多只会扫描到1个
    for (int i = 0; i < ap_number; i++) {
        #ifdef TAG  // debug
        ESP_LOGI(TAG, "SSID: %s", ap_info[i].ssid);
        ESP_LOGI(TAG, "RSSI: %d", ap_info[i].rssi);
        ESP_LOGI(TAG, "Channel: %d", ap_info[i].primary);
        ESP_LOGI(TAG, "BSSID: " MACSTR "", MAC2STR(ap_info[i].bssid) );
        #endif
    }
    esp_wifi_scan_stop(); // from start to stop need 3210ms
    #ifdef TAG  // debug
    ESP_LOGI(TAG,"stop scan\r\n");
    #endif
 
    return ap_info[0].rssi;
#endif    
}

static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data)
{
    if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { 
        ip_event_got_ip_t *evt = (ip_event_got_ip_t *) event_data;
        local_ip_addr.addr = evt->ip_info.ip.addr;
        #ifdef WIFI_MESH_DEBUG_ENABLE
        ESP_LOGI(TAG, "got ip:" IPSTR,  IP2STR(&evt->ip_info.ip));
        ESP_LOGI(TAG, "ip.addr = %08X", evt->ip_info.ip.addr);
        #endif
    }
} 

/**
 * @brief All module events will be sent to this task in esp-mdf
 *
 * @Note:
 *     1. Do not block or lengthy operations in the callback function.
 *     2. Do not consume a lot of memory in the callback function.
 *        The task memory of the callback function is only 4KB.
 */
static mdf_err_t mdf_event_loop_cb(mdf_event_loop_t event, void *ctx)
{
    bool mwifi_connect_update = false; // 连接状态发生变化时，通知节点网络状态！
    switch (event) {
        case MDF_EVENT_MWIFI_STARTED:
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("MDF_EVENT_MWIFI_STARTED...");
            #endif
            xEventGroupSetBits(mwifi_event_group, WIFI_START_EVENT);  
            break;
        case MDF_EVENT_MWIFI_STOPPED:
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("MDF_EVENT_MWIFI_STOPPED...");
            #endif
            xEventGroupSetBits(mwifi_event_group, WIFI_STOP_EVENT);  
            break;
        case MDF_EVENT_MWIFI_PARENT_CONNECTED: {  // 如果是ROOT，说明连接上了路由器，其他节点说明成功组网了！
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("MDF_EVENT_MWIFI_PARENT_CONNECTED");
            #endif
            esp_netif_dhcpc_start(esp_netif);   // 使用WIFI时，一定要放在这，不然MQTT连接不上网络！  
            xEventGroupSetBits(mwifi_event_group, WIFI_CONNECTED_EVENT);  
            xEventGroupClearBits(mwifi_event_group, WIFI_DISCONNECTED_EVENT);  
            mwifi_connect_update = true;
            break;
        }
 
        case MDF_EVENT_MWIFI_PARENT_DISCONNECTED:  // 如果是ROOT，说明没有连接上了路由器，其他节点说明没成功组网！
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("MDF_EVENT_MWIFI_PARENT_DISCONNECTED");
            #endif
            local_ip_addr.addr = 0;  // 断开连接，IP地址清零
            mwifi_connect_update = true;
            xEventGroupSetBits(mwifi_event_group, WIFI_DISCONNECTED_EVENT);  
            xEventGroupClearBits(mwifi_event_group, WIFI_CONNECTED_EVENT);  
            break;

        case MDF_EVENT_MWIFI_CHILD_DISCONNECTED: {
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            mesh_event_info_t *event_info = (mesh_event_info_t *)ctx;
            MDF_LOGI("disconnected child: " MACSTR, MAC2STR(event_info->child_disconnected.mac));
            #endif
            break;
        }

        case MDF_EVENT_MWIFI_ROUTING_TABLE_ADD:
        case MDF_EVENT_MWIFI_ROUTING_TABLE_REMOVE: {
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            mesh_event_info_t *event_info = (mesh_event_info_t *)ctx;
            MDF_LOGI("total_num: %d, changed: %d", esp_mesh_get_total_node_num(), event_info->routing_table.rt_size_change);
            #endif
            event_routing_table = true; // 路由表发生了变化！
            mwifi_connect_update = true;
            break;
        }

        case MDF_EVENT_MWIFI_ROOT_GOT_IP: {
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            ip_event_got_ip_t *event_info = (ip_event_got_ip_t *)ctx;
            local_ip_addr.addr = event_info->ip_info.ip.addr;  
            
            MDF_LOGI("MDF_EVENT_MWIFI_ROOT_GOT_IP -> Root obtains the IP address. ");
            MDF_LOGI("sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
                     IP2STR(&event_info->ip_info.ip),
                     IP2STR(&event_info->ip_info.netmask),
                     IP2STR(&event_info->ip_info.gw));
            #endif 
            break;
        }

        case MDF_EVENT_MWIFI_ROOT_LOST_IP:
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("MDF_EVENT_MWIFI_ROOT_LOST_IP");
            #endif
            break;

        case MDF_EVENT_MWIFI_ROOT_ADDRESS: {  // 获取到ROOT节点的MAC地址
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            mesh_event_info_t *event_info = (mesh_event_info_t *)ctx;
            MDF_LOGI("MDF_EVENT_MWIFI_ROOT_ADDRESS: " MACSTR, MAC2STR(event_info->root_addr.addr));
            #endif
            break;
        }
        default:
            #ifdef WIFI_MESH_DEBUG_ENABLE  // debug
            MDF_LOGI("mdf_event_loop_cb, [default]event: 0x%X", event);
            #endif  
            break;
    }

    // 连接状态发生变化时，通知节点网络状态！
    if (mwifi_connect_update == true) {
        mwifi_connect_update = mwifi_connect_status(0);
        mwifi_post_root_status(mwifi_connect_update);      // 通知其它节点，ROOT节点连接网络状态
    }
    
    return MDF_OK;
}

static mdf_err_t wifi_init(void)
{
    wifi_init_config_t init_config = WIFI_INIT_CONFIG_DEFAULT();

    ESP_ERROR_CHECK(esp_event_loop_create_default());

    // ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));

    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_netif_create_default_wifi_mesh_netifs(&esp_netif, NULL));
    
    ESP_ERROR_CHECK(esp_wifi_init(&init_config));
    ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_FLASH));
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
    ESP_ERROR_CHECK(esp_wifi_set_ps(WIFI_PS_MAX_MODEM));  // must call this  
    ESP_ERROR_CHECK(esp_mesh_set_6m_rate(false));
    ESP_ERROR_CHECK(esp_wifi_start());

    return MDF_OK;
}

static void app_mwifi_set_config(const char router_ssid[32], const char router_password[32])
{
    mwifi_config_t mwifi_cfg = {
        .router_ssid     = { 0 },
        .router_password = { 0 },
        .mesh_id         = { 0 },
        .mesh_password   = CONFIG_MWIFI_PASSWROD,
        .channel         = CONFIG_MWIFI_CHANNEL,
        .channel_switch_disable = false,
        .router_switch_disable = false,
        .mesh_type       = CONFIG_MWIFI_MESH_TYPE,   
    };
    
    memcpy(mwifi_cfg.router_ssid, router_ssid, strlen(router_ssid));
    memcpy(mwifi_cfg.router_password, router_password, strlen(router_password));

    app_mwifi_net_addr(mwifi_cfg.mesh_id);  // 把ROOT节点的MAC当作mesh_id

#ifdef WIFI_MESH_DEBUG_ENABLE  // debug
    printf("\n---------------------------\n");
    ESP_LOGI(TAG, "mwifi_cfg.meshid: " ADDRSTR , ADDR2STR(mwifi_cfg.mesh_id));
    ESP_LOGI(TAG, "mwifi_cfg.ssid: %s", mwifi_cfg.router_ssid);
    ESP_LOGI(TAG, "mwifi_cfg.pass: %s", mwifi_cfg.router_password);
    // MDF_LOGI("esp_netif.route_prio = %d", esp_netif_get_route_prio(esp_netif)); // 上网优先级
    printf("---------------------------\n");
#endif
    MDF_ERROR_ASSERT(mwifi_set_config(&mwifi_cfg));
}

bool app_mwifi_reconnect(const char router_ssid[32], const char router_password[32])
{
    if (selec_network != NETWORK_SELECTION_WIFI) return true;  // 不是wifi上网方式，直接返回OK！

    if (mwifi_connect_status(0) == true) {
        esp_mesh_disconnect();  // Disconnect from current parent.
        mwifi_event_wait(WIFI_DISCONNECTED_EVENT, 500); // 等待断开
    }

    xEventGroupClearBits(mwifi_event_group, WIFI_STOP_EVENT);  // 先清零
    mwifi_stop();
    mwifi_event_wait(WIFI_STOP_EVENT, 500); // 等待停止
 
    app_mwifi_set_config(router_ssid, router_password);  // 重新配置路由器信息

    xEventGroupClearBits(mwifi_event_group, WIFI_START_EVENT);  // 先清零
    mwifi_start();
    mwifi_event_wait(WIFI_START_EVENT, 500); // 等待启动
 
    return mwifi_connect_status(15000);  // 等待连接/15s
}

#if 0
void esp_vendor_ie_cb(void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const vendor_ie_data_t *vnd_ie, int rssi)
{
    ESP_LOGI(TAG, "BSSID: " MACSTR "", MAC2STR(sa) );
    ESP_LOGI(TAG, "esp_vendor_ie_cb->rssi = %d\n\n\n", rssi);
}
#endif 

void app_mwifi_deinit(void) 
{ 
    if (mwifi_connect_status(0) == true) {
        esp_mesh_disconnect();  // Disconnect from current parent.
        mwifi_event_wait(WIFI_DISCONNECTED_EVENT, 500); // 等待断开
    }
    // esp_wifi_stop();
    mwifi_stop(); 
    mwifi_deinit();
}

void app_mwifi_init(nvs_wifi_t nvs_wifi)
{
    selec_network = NETWORK_SELECTION_WIFI;   // 默认选择wifi上网！

    /**
     * @brief Set the log level for serial port printing.
     */
    esp_log_level_set(TAG, ESP_LOG_INFO);
    esp_log_level_set("wifi", ESP_LOG_WARN);
    esp_log_level_set("wifi_init", ESP_LOG_WARN);
    esp_log_level_set("mesh", ESP_LOG_WARN);
    esp_log_level_set("mwifi", ESP_LOG_WARN);

    mwifi_event_group = xEventGroupCreate();

    // 不是选择的WIFI，就必须把WIFI信息清空，WIFI 与 Ethernet 是不能共存的！
    if (selec_network != NETWORK_SELECTION_WIFI || nvs_wifi.status == WIFI_CONFIG_NULL) {
        memset(nvs_wifi.ssid, 0x0, 32);
        memset(nvs_wifi.password, 0x0, 32);  // 清空才不会去连接 WIFI ！！！
    } 

#if 0  // 测试给一个能联网的WIFI
    if (selec_network == NETWORK_SELECTION_WIFI && nvs_wifi.status == WIFI_CONFIG_NULL) {
        // memcpy(nvs_wifi.ssid, "azolla", strlen("azolla"));
        // memcpy(nvs_wifi.password, "1234567800", strlen("1234567800"));  // 设置默认路由器
        memcpy(nvs_wifi.ssid, "yiree-zhulao", strlen("yiree-zhulao"));
        memcpy(nvs_wifi.password, "yiree2021", strlen("yiree2021"));
    }
#endif
  
    /**
     * @brief Initialize wifi mesh.
     */
    mwifi_init_config_t init_config = MWIFI_INIT_CONFIG_DEFAULT();
    MDF_ERROR_ASSERT(mdf_event_loop_init(mdf_event_loop_cb));
    MDF_ERROR_ASSERT(wifi_init());  // 初始化WIFI
    MDF_ERROR_ASSERT(mwifi_init(&init_config));
    app_mwifi_set_config(nvs_wifi.ssid, nvs_wifi.password);
    MDF_ERROR_ASSERT(mwifi_start());  

    /**
     * @brief select/extend a group memebership here
     *        group id can be a custom address
     */
    MDF_ERROR_ASSERT(esp_mesh_set_group_id((mesh_addr_t *)group_id_list, sizeof(group_id_list) / sizeof(group_id_list[0])));

    /* 节点成功连接上父节点后，首次创建对应的任务！ */
    if (esp_mesh_is_root()) {  // 根节点
        mwifi_ota_queue = xQueueCreate(1, sizeof(ota_result_t));
        xTaskCreatePinnedToCore(root_read_task,  "root_read",  3 * 1024, NULL, CONFIG_MDF_TASK_DEFAULT_PRIOTY - 1, NULL, APP_CPU_NUM);   
    } 
}
